package redis

import (
	"context"
	"github.com/go-redis/redis/v8"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	"os"
	"time"
)

var RDB *redis.Client
var Enabled = true

// InitClient 初始化Redis连接
func InitClient() (err error) {
	if os.Getenv("REDIS_CONN_STRING") == "" {
		Enabled = false
		logrus.Infoln("未设置REDIS_CONN_STRING, Redis未启用")
		return nil
	}
	logrus.Infoln("Redis已启用")
	opt, err := GetOpt()
	if err != nil {
		logrus.Infoln("未能正确解析REDIS_CONN_STRING: " + err.Error())
	}
	RDB = redis.NewClient(opt)

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	_, err = RDB.Ping(ctx).Result()
	if err != nil {
		logrus.Infoln("Redis测试失败: " + err.Error())
	}
	return err
}

// Set 保存字符串到redis
// key 键
// value 值
func Set(key string, value string, expiration time.Duration) error {
	if err := checkRedis(); err != nil {
		return err
	}
	ctx := context.Background()
	return RDB.Set(ctx, key, value, expiration).Err()
}

// Get 从redis读取字符串
// key 键
func Get(key string) (string, error) {
	if err := checkRedis(); err != nil {
		return "", err
	}
	ctx := context.Background()
	return RDB.Get(ctx, key).Result()
}

// Del 从redis删除键
// key 键
func Del(key string) error {
	if err := checkRedis(); err != nil {
		return err
	}
	ctx := context.Background()
	return RDB.Del(ctx, key).Err()
}

// Scan 扫描redis
// keyword 关键词，支持通配
func Scan(keyword string) ([]string, error) {
	if err := checkRedis(); err != nil {
		return nil, err
	}
	ctx := context.Background()

	var keys []string
	var cursor uint64
	for {
		var err error
		var k []string
		k, cursor, err = RDB.Scan(ctx, cursor, keyword, 0).Result()
		if err != nil {
			return nil, err
		}
		keys = append(keys, k...)
		// 如果cursor为0，表示遍历完成
		if cursor == 0 {
			break
		}
	}
	return keys, nil
}

// checkRedis 检测redis是否已启用
func checkRedis() error {
	if !Enabled {
		return errors.New("redis未启用")
	}
	return nil
}

// GetOpt 从环境变量获取redis配置
func GetOpt() (*redis.Options, error) {
	return redis.ParseURL(os.Getenv("REDIS_CONN_STRING"))
}
